package auth

import (
	"context"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	userx "mall/service/user/rpc/types/user"

	"github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type CreateUserAuthInfoLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCreateUserAuthInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateUserAuthInfoLogic {
	return &CreateUserAuthInfoLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *CreateUserAuthInfoLogic) CreateUserAuthInfo(in *userx.TmpUserAuthInfo) (*userx.BaseUserResp, error) {
	if in.PlatformId == nil || *in.PlatformId == 0 {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	if in.Openid == nil || len(strings.TrimSpace(*in.Openid)) == 0 {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	platformId := *in.PlatformId
	openId := strings.TrimSpace(*in.Openid)

	// 查询用户是否存在
	filterMap := make(map[string]map[string][]any)
	filterMap[model.UserAuthColumns.PlatformID] = map[string][]any{
		"equalTo": []any{platformId},
	}
	filterMap[model.UserAuthColumns.Openid] = map[string][]any{
		"equalTo": []any{openId},
	}

	selectCols := []string{
		model.UserAuthColumns.UserAuthID,
		model.UserAuthColumns.UserID,
	}
	authList, _, err := l.svcCtx.CurrentUser.GetAuthList(l.ctx, model.M{
		"pageSize": uint64(1),
		"select":   strings.Join(selectCols, ","),
		"orderBy":  model.UserAuthColumns.UserAuthID + " DESC",
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	if len(authList) > 0 {
		return nil, resultx.StatusError(resultx.USER_EXISTS, "")
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.DB_ERROR, "")
	}

	now := time.Now()
	user := &model.User{
		UserStatus: uint16(globalkey.StatusEnabled),
		CreatedAt:  now,
		UpdatedAt:  now,
	}
	if in.CreatedIP != nil && len(strings.TrimSpace(*in.CreatedIP)) > 0 {
		user.CreateIP = strings.TrimSpace(*in.CreatedIP)
	}

	userAuth := &model.UserAuth{
		PlatformID: uint(platformId),
		Openid:     openId,
		CreatedAt:  now,
		UpdatedAt:  now,
	}

	userDetail := &model.UserDetail{}

	var userMeta []*model.UserMetum

	if in.Unionid != nil && len(strings.TrimSpace(*in.Unionid)) > 0 {
		userAuth.Unionid = strings.TrimSpace(*in.Unionid)
	}
	if in.SessionKey != nil && len(strings.TrimSpace(*in.SessionKey)) > 0 {
		userAuth.SessionKey = strings.TrimSpace(*in.SessionKey)
	}
	if in.Nickname != nil && len(strings.TrimSpace(*in.Nickname)) > 0 {
		userAuth.Nickname = strings.TrimSpace(*in.Nickname)
		userDetail.Nickname = userAuth.Nickname
		userMeta = append(userMeta, &model.UserMetum{
			MetaKey:   "authorized",
			MetaValue: null.StringFrom("1"),
		})
	}
	if in.Avatar != nil && len(strings.TrimSpace(*in.Avatar)) > 0 {
		userAuth.Avatar = strings.TrimSpace(*in.Avatar)
		userDetail.Avatar = userAuth.Avatar
	}
	if in.Gender != nil && *in.Gender > 0 {
		userAuth.Gender = uint8(*in.Gender)
		userDetail.Gender = userAuth.Gender
	}
	if in.Country != nil && len(strings.TrimSpace(*in.Country)) > 0 {
		userAuth.Country = strings.TrimSpace(*in.Country)
		userDetail.Country = userAuth.Country
	}
	if in.Province != nil && len(strings.TrimSpace(*in.Province)) > 0 {
		userAuth.Province = strings.TrimSpace(*in.Province)
		userDetail.Province = userAuth.Province
	}
	if in.City != nil && len(strings.TrimSpace(*in.City)) > 0 {
		userAuth.City = strings.TrimSpace(*in.City)
		userDetail.City = userAuth.City
	}
	if in.Language != nil && len(strings.TrimSpace(*in.Language)) > 0 {
		userAuth.Language = strings.TrimSpace(*in.Language)
		userDetail.Language = userAuth.Language
	}
	if in.Authorized != nil && *in.Authorized > 0 {
		userAuth.Status = uint8(*in.Authorized)
	}
	if in.Mobile != nil && len(strings.TrimSpace(*in.Mobile)) > 0 {
		userAuth.Mobile = strings.TrimSpace(*in.Mobile)
		user.UserMobile = userAuth.Mobile
	}
	if in.Birthday != nil && len(strings.TrimSpace(*in.Birthday)) > 0 {
		if localTime, err := modelx.ParseLocalDate(strings.TrimSpace(*in.Birthday)); err == nil {
			userAuth.Birthday = null.TimeFrom(localTime)
			userDetail.Birthday = userAuth.Birthday
		}
	}

	err = l.svcCtx.CurrentUser.Insert(l.ctx, tx, user, &model.UserRel{
		Auth:   userAuth,
		Detail: userDetail,
		Meta:   userMeta,
	})
	if err != nil {
		tx.Rollback()
		return nil, resultx.StatusError(resultx.USER_REGISTER_FAILED, "")
	}

	tx.Commit()

	return &userx.BaseUserResp{
		Id:     pointy.GetPointer(strconv.FormatInt(int64(user.ID), 10)),
		Status: pointy.GetPointer(uint32(user.UserStatus)),
		RankId: pointy.GetPointer(uint64(globalkey.DefaultMemberRankId)),
		Role:   pointy.GetPointer(uint32(globalkey.DefaultMemberRole)),
	}, nil
}
